/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MathLib.HashMatrix;

import java.util.ArrayList;

/**
 *
 * @author marko
 */
public class HashMatrix extends Matrix{
      // тип хранения данных: массив или хэш-таблица
      public static byte ARRAY_TYPE = 0;
      public static byte HASH_TYPE = 1;
      // jp - строки верхней полуматрицы
      // jm - столбцы нижней полуматрицы
      // dd - главная диагональ
      private IRow[] jp,jm;
      private double[] dd;
      // конструктор матрицы
      // type - тип хранения данных ARRAY_TYPE/HASH_TYPE
      // N - порядок матрицы
      public HashMatrix(byte type, int N){
        super(N);
        dd = new double[N];
        if (type==HASH_TYPE){
            jp = new Hash[N];
            jm = new Hash[N];
            for (int i=0; i<N; i++){
                jp[i] = new Hash();
                jm[i] = new Hash();
            }
        }else{
            jp = new Array[N];
            jm = new Array[N];
            for (int i=0; i<N; i++){
                jp[i] = new Array();
                jm[i] = new Array();
            }
        }
      }

       public void setValue(int row, int col, double value){
            if (row==col){
                dd[row] = value;
                return;
            }
            int d = getD(row,col);
            int j = getJ(row,col);
            if (j>0) jp[d].setValue(j,value);
            else jm[d].setValue(-j,value);
      }

      public void addValue(int row, int col, double value){
            if (value==0) return;
            if (row==col){
                dd[row] += value;
                return;
            }
            int d = getD(row,col);
            int j = getJ(row,col);
            if (j>0) jp[d].addValue(j, value);
            else jm[d].addValue(-j,value);
      }

      public double getValue(int row, int col){
            if (row==col) return dd[row];
            int d = getD(row,col);
            int j = getJ(row,col);
            return (j>0)?jp[d].getValue(j):jm[d].getValue(-j);
      }

      public void getJRow(int d, int[] indexes, double[] values){
            jp[d].getValues( indexes,  values);
            for (int i=0; i<indexes.length; i++){
                indexes[i] = getCol(d,indexes[i]);
            }
      }

      public void getJCol(int d, int[] indexes, double[] values){
            jm[d].getValues(indexes, values);
            for (int i=0; i<indexes.length; i++){
                indexes[i] = getRow(d,-indexes[i]);
            }

      }

    public void getJCol(int d, ArrayList<Integer> indexes, ArrayList<Double> values) {
        indexes = jm[d].getIndexes();
        values = jm[d].getValues();
        for (int i=0; i<indexes.size(); i++){
            indexes.set(i, getRow(d,-indexes.get(i)));
        }
    }

    public ArrayList<Integer> getJColIndex(int d) {
        ArrayList<Integer> indexes = jm[d].getIndexes();
        for (int i=0; i<indexes.size(); i++){
            indexes.set(i, getRow(d,-indexes.get(i)));
        }
        return indexes;
    }

    public ArrayList<Double> getJColValues(int d) {
        return jm[d].getValues();
    }

    public ArrayList<Integer> getJRowIndex(int d) {
        ArrayList<Integer> indexes = jp[d].getIndexes();
        for (int i=0; i<indexes.size(); i++){
            indexes.set(i, getCol(d,indexes.get(i)));
        }
        return indexes;
    }

    public ArrayList<Double> getJRowValues(int d) {
        return jp[d].getValues();
    }

}
